var AudioManager = cc.Class({
    extends: cc.Component,

    properties: {
    },
    statics: {
        // 预定义一些音频组
        // AudioType:cc.Enum({
        //     MUSIC: 'music',
        //     SFX: 'sfx',
        //     VOICE: 'voice',
        // }),
        // 单例
        Singleton: null,
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        if (!AudioManager.Singleton)
            AudioManager.Singleton = this;
        else
            this.destroy();
    },
    /**
     * 播放音乐类音频
     * @param {cc.AudioClip} audioClip 
     * @param {number} numLoops 播放次数，小于1则无限循环。 
     * @param {number} volumn 
     * @param {function} complete  
     */
    playMusic(audioClip, numLoops, volumn, complete) {
        return this.play(AudioManager.AudioType.MUSIC//AudioManager.AudioType.MUSIC
            , audioClip, numLoops, volumn, complete);
    },
    /**
     * 播放音效类音频
     * @param {cc.AudioClip} audioClip 
     * @param {number} numLoops 播放次数，小于1则无限循环。 
     * @param {number} volumn 
     * @param {function} complete   
     */
    playSFX(audioClip, numLoops, volumn, complete) {
        return this.play(AudioManager.AudioType.SFX//AudioManager.AudioType.SFX
            , audioClip, numLoops, volumn, complete);
    },
    /**
     * 播放语音类音频
     * @param {cc.AudioClip} audioClip 
     * @param {number} numLoops 播放次数，小于1则无限循环。 
     * @param {number} volumn 
     * @param {function} complete  
     */
    playVoice(audioClip, numLoops, volumn, complete) {
        return this.play(AudioManager.AudioType.VOICE//AudioManager.AudioType.VOICE
            , audioClip, numLoops, volumn, complete);
    },
    /**
     * 停止所有音频播放
     */
    stopAll(){
        cc.audioEngine.stopAll();
    },
    /**
     * 停止音乐类音频
     */
    stopMusic(){
        this.stop(AudioManager.AudioType.MUSIC);
    },
    /**
     * 停止音效类音频
     */
    stopSFX(){
        this.stop(AudioManager.AudioType.SFX);
    },
    /**
     * 停止语音类音频
     */
    stopVoice(){
        this.stop(AudioManager.AudioType.VOICE);
    },
    /**
     * 获取音乐类音频的总控音量
     */
    getMusicVolumn(){
        return this.getGroupVolumn(AudioManager.AudioType.MUSIC);
    },
    /**
     * 获取音乐类音频的总控音量
     */
    getSFXVolumn(){
        return this.getGroupVolumn(AudioManager.AudioType.SFX);
    },
    /**
     * 获取音乐类音频的总控音量
     */
    getVoiceVolumn(){
        return this.getGroupVolumn(AudioManager.AudioType.VOICE);
    },
    /**
     * 设置音乐类音频的总音量
     * @param {number} volumn 
     */
    setMusicVolumn(volumn){
        this.setGroupVolumn(AudioManager.AudioType.MUSIC, volumn);
    },
    /**
     * 设置音效类音频的总音量
     * @param {number} volumn 
     */
    setSFXVolumn(volumn){
        this.setGroupVolumn(AudioManager.AudioType.SFX, volumn);
    },
    /**
     * 设置语音类音频的总音量
     * @param {number} volumn 
     */
    setVoiceVolumn(volumn){
        this.setGroupVolumn(AudioManager.AudioType.VOICE, volumn);
    },
    /**
     * 在指定到音乐组播放音频，不存在到音频组会被自动创建
     * @param {string} groupName
     * @param {cc.AudioClip} audioClip 
     * @param {number} numLoops，循环次数，小于等于0，则为无限循环 
     * @param {number} volumn 
     * @param {function} complete 
     * @return {number} 返回播放的audio id
     */
    play(groupName, audioClip, numLoops, volumn, complete){
        //
        if ( numLoops === undefined || numLoops === null || numLoops === false)
            numLoops = 1;
        // 兼容
        if ( numLoops === true)
            numLoops = -1;
        //
        var infiniteLoop = (numLoops < 1);
        //
        var audioId = this._playImpl(groupName, audioClip, infiniteLoop, volumn);
        // 不是无限循环，计算事件，调用回调
        if (infiniteLoop === false) {
            var duration = cc.audioEngine.getDuration(audioId) * numLoops;
            this.scheduleOnce((()=>{
                // 若声音未停止，则停止
                var audioState = cc.audioEngine.getState(audioId);
                if (audioState === cc.audioEngine.AudioState.PLAYING)
                    this.stopAudio(audioId);
                // 调用播放结束回调
                complete && complete();
            }).bind(this), duration);
        }
        //
        return audioId;
    },
    /**
     * 在指定到音乐组播放音频，不存在到音频组会被自动创建
     * @param {string} groupName
     * @param {cc.AudioClip} audioClip 
     * @param {bool} loop 是否循环
     * @param {number} volumn 
     * @param {function} complete 
     * @return {number} 返回播放的audio id
     */
    _playImpl(groupName, audioClip, loop, volumn, complete) {
        // 获取音频组，不存在则创建
        var group = this._getGroup(groupName, true);
        // 获取该音频组的音量
        var groupVolumn = group.volumn;
        // 融合传入的音量
        (void 0 === volumn) && (volumn = 1);
        var mixedVolumn = this._validateVolumn(volumn * groupVolumn);
        // 播放音频
        var id = cc.audioEngine.play(audioClip, loop, mixedVolumn);
        // // var id = cc.audioEngine.playMusic(audioClip, loop, mixedVolumn);
        // var id = cc.audioEngine.playEffect(audioClip, loop, mixedVolumn);
        // 处理结束回调
        if (complete || true) { // 可能2.0.1对于audioPool的处理存在bug，因此这里主动将不需要的complete设置成null
            cc.audioEngine.setFinishCallback(id, complete);
        }
        // 添加音频信息到组
        group.audios[id] = {
            id: id,
            clip: audioClip,
            volumn: volumn
        };
        // 返回audio id
        return id;
    },
    clearFinishCallback(audioID){
        cc.audioEngine.setFinishCallback(audioID)
    },
    _audioOp(groupName, op){
        var group = this._getGroup(groupName);
        if (group){
            for( var audioID in group.audios)
                op(audioID);
        }
    },
    pause(groupName){
        this._audioOp(groupName, this.pauseAudio.bind(this));
    },
    resume(groupName){
        this._audioOp(groupName, this.resumeAudio.bind(this));
    },
    stop(groupName){
        this._audioOp(groupName, this.stopAudio.bind(this));
    },
    pauseAudio(audioID){
        cc.audioEngine.pause(audioID);
    },
    resumeAudio(audioID){
        cc.audioEngine.resume(audioID);
    },
    stopAudio(audioID){
        cc.audioEngine.stop(audioID);
    },
    /**
     * 获取音频组的音量，如果不存在则创建
     * @param {string} groupName 
     */
    getGroupVolumn(groupName) {
        return this._getGroup(groupName,  true).volumn;
    },
    /**
     * 设置音频组音频音量，该组正在播放到音频音量都将被影响
     * @param {string} groupName 
     * @param {number} volumn 
     */
    setGroupVolumn(groupName, volumn) {
        volumn = this._validateVolumn(volumn);
        var g = this._getGroup(groupName, true);
        g.volumn = volumn;
        // 重新设置所有音频音量
        for (var id in g.audios) {
            var audio = g.audios[id];
            var mixedVolumn = this._validateVolumn(g.volumn * audio.volumn);
            cc.audioEngine.setVolume(id, mixedVolumn);
        }
    },
    /**
     * 获取audioID到音量
     * @param {number} audioID
     * @return {number} -1 说明未找到audioID对应到音频信息
     */
    getAudioVolumn(audioID){
        var audio = this._getAudio(audioID);
        if (audio)
            return audio.volumn;
        else
            return -1;
    },
    /**
     * 
     * @param {number} audioID 
     * @param {number} volumn 
     */
    setAudioVolumn(audioID, volumn){
        var group = this._getGroupByAudioID(audioID);
        if (!group)
            return;
        var audio = group.audios[audioID];
        audio.volumn = volumn;
        var mixedVolumn = this._validateVolumn(group.volumn * audio.volumn);
        cc.audioEngine.setVolume(audioID, mixedVolumn);
    },
    /////////////////Private Methods/////////////////
    /**
     * 获取音频组
     * @param {string} groupName 
     * @param {bool} createIfNotExists 不存在是否自动创建
     */
    _getGroup(groupName, createIfNotExists) {
        // 如果group属性不存在，就创建它
        this._groups = this._groups || {};
        if (!createIfNotExists && !this._groups[groupName])
            return;
        // 如果groupName对应的音频组不存在，就创建
        this._groups[groupName] = this._groups[groupName] || {
            // audios中是以audioID为索引到audio信息
            audios: {
                // 'audioID':
                // {
                //       id: audioID,
                //     clip: audioClip,
                //   volumn: localVolumn
                // }
            },
            volumn: 1
        }
        //
        return this._groups[groupName];
    },
    /**
     * 获取指定audioID到音频信息
     * @param {number} audioID 
     */
    _getAudio(audioID){
        var group = this._getGroupByAudioID(audioID);
        if (group)
            return group[audioID];
        //
        return null;
    },
    _getGroupByAudioID(audioID){
        // 便利各个音频组找到audio信息
        for (var groupName in this._groups) {
            var group = this._groups[groupName];
            if (group.audios[audioID]) {
                return group;
            }
        }
        return null;
    },
    /**
     * 将volumn限制在0到1之间
     * @param {number} volumn 
     */
    _validateVolumn(volumn) {
        return Math.min(Math.max(0, volumn), 1);
    },
    /**
     * 从指定group中获得指定audioID到audio信息
     * @param {number} audioID 
     * @param {string} groupName 
     */
    _getAudioFromGroup(audioID, groupName) {
        var group = this._getGroup(groupName);
        var audio = group || group[audioID];
        return audio;
    },
    onDestroy(){
        this.stopAll();
    }

    // update (dt) {},
});

AudioManager.AudioType = cc.Enum({
    MUSIC: 0,
    SFX: 1,
    VOICE: 2,
});

module.exports = AudioManager;
